<template>
  <span
    class="var-value-col"
    :title="row?.constraintMessage || ''"
  >
    <el-checkbox
      v-if="row.valueType === 'Boolean'"
      v-model="booleanValue"
      true-label="true"
      false-label="false"
      size="small"
      :class="{
        'radio-position': true,
        'red-border': invalidValue,
      }"
      :disabled="
        !['Integer', 'Real', 'Boolean', 'String'].includes(row.valueType)
      "
      @change="updateVariableValue(booleanValue)"
    >
      {{ row.value }}
    </el-checkbox>
    <el-select
      v-else-if="row.valueType === 'Enumeration'"
      v-model="row.value"
      class="m-2"
      placeholder="Select"
      size="small"
      @change="updateVariableValue(row.value)"
    >
      <el-option
        v-for="(item, index) in selectOptions"
        :key="index"
        :label="item.label"
        :value="item.value"
      />
    </el-select>

    <el-input
      v-else
      v-model="row.value"
      :disabled="row.disabled"
      size="small"
      :class="{
        'red-border': invalidValue,
      }"
      @blur="updateVariableValue(row.value)"
      @keyup.enter="updateVariableValue(row.value)"
    >
      {{ row.value }} {{ row.modelVo.type }}
    </el-input>
  </span>
</template>

<script lang="ts" setup>
import { onMounted, reactive, ref } from "vue";
import { ipcRenderer } from "electron";

import { controller } from "@/engine/Controller";
import { VariableData } from "@/engine/_";
import { EnumerationValue } from "@/engine/types/variable";
import { TimeSeryMountedStorageData } from "@/engine/types/charts";
import { SimFrameToSubChannel, SubWinName } from "@/engine/types/Win";
import { modelHttp } from "@/util/httpClient/ModelNodeHttpClient";
import { API } from "@/constants/api";
import { PropertyKey } from "@/constants/constants";
import { IpcMsg } from "@/engine/types/Ipc";
import { watch } from "vue";

const props = withDefaults(defineProps<{ row: VariableData }>(), {});

const selectOptions = reactive<EnumerationValue[]>([]);
let nodeDataOldValue = props.row.value as string;
let booleanValue = ref(props.row.value === "true");
const invalidValue = ref(false);

onMounted(async () => {
  if (props.row.valueType === 'Enumeration') {
    const checkResult = await controller.variableService.getEnumerationDefaultAndItems(props.row.value);
    selectOptions.push(...checkResult.data);
    if (checkResult.isEnum) {
      props.row.value = '';
    }
  }
});

watch(
  () => props.row.value,
  (v) => {
    // extensive for checkbox model
    if (props.row?.valueType === 'Boolean') {
      booleanValue.value = v === 'true';
      nodeDataOldValue = v;
    }
  }
);

const updateVariableValue = async (value: string | number | boolean) => {
  if (String(value) !== nodeDataOldValue) {
    let useValueId = props.row.valueId;
    if (useValueId.includes("@@")) {
      useValueId = useValueId.split("@@")[0];
    }
    let isUpdateSuccess;
    if (String(value) && useValueId) {
      isUpdateSuccess = await controller.variableService.updateVariable({
        valueId: useValueId,
        index: props.row.mindex,
        value,
        ov: nodeDataOldValue,
      });
    } else {
      isUpdateSuccess = await controller.simApi.variableRemove({
        simulationSessionId: controller.sessionId,
        sceneId: controller.sceneId,
        valueId: useValueId,
        index: props.row.mindex!,
      });
    }

    if (isUpdateSuccess) {
      nodeDataOldValue = value as string;
    } else {
      // 恢复旧的值
      props.row.value = nodeDataOldValue;
    }
  }
};

const variableMethodMap: { [key: string]: () => void } = {
  exportToNew: () => {
    controller.variableService.exportToNew(
      props.row.valueId,
      props.row.isRoot!
    );
  },
  exportToExisted: () => {
    controller.variableService.exportAtExisted(
      props.row?.modelId,
      props.row?.valueId
    );
  },
  exportInteraction: async () => {
    const { data } = await modelHttp.get({
      api: API.QUERY_MODEL_INFO,
      data: {
        projectId: controller.projectId,
        modelId: props.row.modelVo.id,
      },
    });
    let usedData = data?.data;
    if (usedData.baseSt && usedData.baseSt.includes("PartProperty")) {
      // partproperty's baseSt change to it's target's baseSt
      const targetModel = await controller.modelApi.modelPropertyByKey({
        projectId: controller.projectId,
        modelId: props.row?.modelVo.id,
        key: PropertyKey.TypedElement_type,
      });
      if (targetModel?.value) {
        usedData = targetModel.value;
      }
    }
    if (usedData.ownerId) {
      ipcRenderer.send(IpcMsg.MessageChannel, {
        windowName: "MainWindow",
        msg: {
          type: "SimCreateInteraction",
          data: {
            modelId: usedData.id,
            modelName: usedData.name,
            ownerId: usedData.ownerId,
            metaclass: usedData.metaclass,
            baseSt: usedData.baseSt,
            sts: usedData.sts,
          },
        },
      });
    }
  },
  removeValue: async () => {
    await controller.simApi.variableRemove({
      simulationSessionId: controller.sessionId,
      sceneId: controller.sceneId,
      valueId: props.row.valueId,
      index: props.row.mindex || 0,
    });
    props.row.value = "";
  },
  addValue: async () => {
    await controller.variableService.updateVariable({
      valueId: props.row.valueId,
      ov: nodeDataOldValue,
      index: props.row.mindex,
    });
  },
  openTimeSeriesChart: () => {
    controller.chartsService.openChartWinDirectly(
      props.row.valueId,
      props.row?.modelVo.name,
      (data: TimeSeryMountedStorageData) => {
        if (
          controller.chartsService.timeSeryService.updateByVariablePanelTimer
        ) {
          clearInterval(
            controller.chartsService.timeSeryService.updateByVariablePanelTimer
          );
          controller.chartsService.timeSeryService.timesRecord = 0;
        }
        const propDataInfo = controller.variableService.variableDataMap.get(
          props.row.valueId
        );
        controller.winService.sendInfoToSubWins(
          {
            type: SimFrameToSubChannel.UpdateChartsData,
            data: {
              isDirect: true,
              statusinfo: {
                constraintMessage: propDataInfo?.constraintMessage,
                status: propDataInfo?.status,
              },
              values: [
                controller.chartsService.timeSeryService.timesRecord,
                propDataInfo?.value || 0,
              ],
            },
          },
          SubWinName.Charts
        );
        controller.chartsService.timeSeryService.updateByVariablePanelTimer =
          window.setInterval(() => {
            const propDataInfo = controller.variableService.variableDataMap.get(
              props.row.valueId
            );
            controller.chartsService.timeSeryService.timesRecord += 1000;
            controller.winService.sendInfoToSubWins(
              {
                type: SimFrameToSubChannel.UpdateChartsData,
                data: {
                  statusinfo: {
                    constraintMessage: propDataInfo?.constraintMessage,
                    status: propDataInfo?.status,
                  },
                  values: [
                    controller.chartsService.timeSeryService.timesRecord,
                    propDataInfo?.value || 0,
                  ],
                },
              },
              SubWinName.Charts
            );
          }, 1000);
      }
    );
  },
};

// const variableInputFocus = (value: string | number | boolean) => {
//   if (!value) {
//     variableMethodMap.addValue();
//   }
// };
</script>

<style lang="scss">
.var-value-col {
  width: 100%;
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  align-items: center;

  .el-select {
    width: 97%;
  }
  .el-input {
    .el-input__inner {
      border: none;
      width: 100%;
    }
  }
  .el-input__inner {
    height: 24px;
  }

  .el-checkbox {
    height: 16px;
    margin-top: 4px;
  }
  .is-focus {
    .el-input__inner {
      border: 1px solid #409eff;
      width: 100%;
    }
  }
  .radio-position {
    margin-left: 10px;
  }
  .red-border {
    border-color: rgb(248, 226, 221);
  }
}
</style>
